// CrossModalDialog.cpp : implementation file
//

#include "stdafx.h"
#include "ImageLab.h"
#include "CrossModalDialog.h"
#define IMAGESTARTX 11
#define IMAGEENDX (11+314)
#define STARTY 48
#define ENDY (48+200)
#define LINGUISTICSTARTX (24+314)
#define LINGUISTICENDX (24+314*2)
#include "ImageAnnotation.h"
#include "ChildFrm.h"

// CCrossModalDialog dialog

IMPLEMENT_DYNAMIC(CCrossModalDialog, CDialog)

CCrossModalDialog::CCrossModalDialog(CWnd* pParent)
	: CDialog(CCrossModalDialog::IDD, pParent)
{
	ASSERT(pParent!=NULL);
	dialogid = CCrossModalDialog::IDD;
	parent = pParent;
	::AfxInitRichEdit2();
}

CCrossModalDialog::~CCrossModalDialog()
{
}

void CCrossModalDialog::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CCrossModalDialog, CDialog)
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_BN_CLICKED(IDC_CROSSMODAL_TRAIN, &CCrossModalDialog::OnBnClickedCrossmodalTrain)
	ON_LBN_SELCHANGE(IDC_CROSSMODAL_IMAGELIST, &CCrossModalDialog::OnLbnSelchangeCrossmodalImagelist)
	ON_BN_CLICKED(IDC_CROSSMODAL_LOAD, &CCrossModalDialog::OnBnClickedCrossmodalLoad)
	ON_LBN_SELCHANGE(IDC_CROSSMODAL_LINGUISTICLIST, &CCrossModalDialog::OnLbnSelchangeCrossmodalLinguisticlist)
	ON_BN_CLICKED(IDC_CROSSMODAL_RETRIEVEIMAGE, &CCrossModalDialog::OnBnClickedCrossmodalRetrieveimage)
	ON_BN_CLICKED(IDC_CROSSMODAL_ADDIMAGE, &CCrossModalDialog::OnBnClickedCrossmodalAddimage)
END_MESSAGE_MAP()

BOOL CCrossModalDialog::Create()
{
	BOOL createstatus = CDialog::Create(dialogid, parent);
	if(createstatus==FALSE)
		return FALSE;

	COLORREF systemcolour = ::GetSysColor(COLOR_3DFACE);

	//Set colour
	BLANKCOLOUR.rgbRed = 255;
	BLANKCOLOUR.rgbGreen = 255;
	BLANKCOLOUR.rgbBlue = 255;

	SELECTCOLOUR.rgbRed = 0;
	SELECTCOLOUR.rgbGreen = 0;
	SELECTCOLOUR.rgbBlue = 255;

	BACKGROUNDCOLOUR.rgbRed = 57;
	BACKGROUNDCOLOUR.rgbGreen = 184;
	BACKGROUNDCOLOUR.rgbBlue = 194;

	LINECOLOUR.rgbRed = 195;
	LINECOLOUR.rgbGreen = 227;
	LINECOLOUR.rgbBlue = 229;

	BOUNDARYCOLOUR.rgbRed = 146;
	BOUNDARYCOLOUR.rgbGreen = 233;
	BOUNDARYCOLOUR.rgbBlue = 140;

	//Create the som view for images and text
	imageview.Create(314, 200, 24, 0);
	linguisticview.Create(314, 200, 24, 0);
	imagelpa = new rgb*[imageview.GetHeight()];
	linguisticlpa = new rgb*[linguisticview.GetHeight()];

	//Plot the background
	imagelparecovery = new rgb*[imageview.GetHeight()];
	linguisticlparecovery = new rgb*[linguisticview.GetHeight()];
	for(int j=0; j<imageview.GetHeight(); j++)
	{
		imagelpa[j] = (rgb*)imageview.GetPixelAddress(0, j);
		linguisticlpa[j] = (rgb*)linguisticview.GetPixelAddress(0, j);
		imagelparecovery[j] = new rgb[imageview.GetWidth()];
		linguisticlparecovery[j] = new rgb[linguisticview.GetWidth()];
		for(int i=0; i<imageview.GetWidth(); i++)
		{
			imagelpa[j][i] = BACKGROUNDCOLOUR;
			linguisticlpa[j][i] = BACKGROUNDCOLOUR;
		}
	}

	//Create the static edge
	rgb outcolour = {127, 157, 185};
	rgb frontcolour = {113, 111, 100};
	rgb backcolour = {241, 249, 226};
	//Outer layer
	for(int j=0; j<imageview.GetHeight(); j++)
	{
		imagelpa[j][0] = outcolour;
		imagelpa[j][imageview.GetWidth()-1] = outcolour;
		linguisticlpa[j][0] = outcolour;
		linguisticlpa[j][imageview.GetWidth()-1] = outcolour;

	}
	for(int i=0; i<imageview.GetWidth(); i++)
	{
		imagelpa[0][i] = outcolour;
		imagelpa[imageview.GetHeight()-1][i] = outcolour;
		linguisticlpa[0][i] = outcolour;
		linguisticlpa[imageview.GetHeight()-1][i] = outcolour;
	}
	//Front colour
	for(int j=1; j<imageview.GetHeight()-2; j++)
	{
		imagelpa[j][1] = frontcolour;
		linguisticlpa[j][1] = frontcolour;
	}
	for(int i=1; i<imageview.GetWidth()-2; i++)
	{
		imagelpa[1][i] = frontcolour;
		linguisticlpa[1][i] = frontcolour;
	}
	//Back colour
	for(int j=1; j<imageview.GetHeight()-2; j++)
	{
		imagelpa[j][imageview.GetWidth()-2] = backcolour;
		linguisticlpa[j][imageview.GetWidth()-2] = backcolour;
	}
	for(int i=1; i<imageview.GetWidth()-2; i++)
	{
		imagelpa[imageview.GetHeight()-2][i] = backcolour;
		linguisticlpa[imageview.GetHeight()-2][i] = backcolour;
	}

	//Initialize the SOM
	linguisticsom = NULL;
	hebbianlink = NULL;
	multiscalenet = NULL;
	crossmodal = NULL;
	linguisticprocessing = NULL;

	return createstatus;
}

void CCrossModalDialog::OnPaint()
{
	CPaintDC dc(this);
	linguisticview.StretchBlt(dc, LINGUISTICSTARTX, STARTY, linguisticview.GetWidth(), linguisticview.GetHeight(), SRCCOPY);
	imageview.StretchBlt(dc, IMAGESTARTX, STARTY, imageview.GetWidth(), imageview.GetHeight(), SRCCOPY);
}

//Plot the view of the image som
void CCrossModalDialog::PlotImageSOM(unsigned int rows, unsigned int columns)
{
	unsigned int m_width = (unsigned int)imageview.GetWidth();
	unsigned int m_height = (unsigned int)imageview.GetHeight();
	//Calcualte the units of nodes
	unsigned int u_x = m_width/(rows+1);
	unsigned int u_y = m_height/(columns+1);
	unsigned int s_x = (m_width%(rows+1))/2;
	unsigned int s_y = (m_height%(columns+1))/2;
	//Plot the lines connecting the nodes
	for(unsigned int i=u_x+s_x; i<m_width-(m_width%(rows+1))+s_x; i=i+u_x)
	{
		for(unsigned int j=u_y+s_y; j<m_height-(m_height%(columns+1)+u_y)+s_y; j++)
		{
			imagelpa[j][i] = LINECOLOUR;
		}
	}
	for(unsigned int j=u_y+s_y; j<m_height-(m_height%(columns+1))+s_y; j=j+u_y)
	{
		for(unsigned int i=u_x+s_x; i<m_width-(m_width%(rows+1)+u_x)+s_x; i++)
		{
			imagelpa[j][i] = LINECOLOUR;
		}
	}
	//Get the position of nodes on the SOM
	imagenodeposition.resize(rows);

	for(unsigned int i=0; i<rows; i++)
	{
		imagenodeposition[i].resize(columns);
		for(unsigned int j=0; j<columns; j++)
		{
			imagenodeposition[i][j].left = u_x*(i+1)-u_x/4+s_x;
			imagenodeposition[i][j].right = u_x*(i+1)+u_x/4+s_x;
			imagenodeposition[i][j].top = u_y*(j+1)-u_y/4+s_y;
			imagenodeposition[i][j].bottom = u_y*(j+1)+u_y/4+s_y;
		}
	}
	//Plot the nodes
	for(unsigned int i=0; i<rows; i++)
	{
		for(unsigned int j=0; j<columns; j++)
		{
			DrawImageNode(imagenodeposition[i][j], BLANKCOLOUR);
		}
	}
	RECT updaterect = {IMAGESTARTX, STARTY, IMAGEENDX, ENDY};
	InvalidateRect(&updaterect, 0);
	UpdateWindow();
	return;
}

//Plot the view of the linguistic som
void CCrossModalDialog::PlotLinguisticSOM(unsigned int rows, unsigned int columns)
{
	unsigned int m_width = (unsigned int)linguisticview.GetWidth();
	unsigned int m_height = (unsigned int)linguisticview.GetHeight();
	//Calcualte the units of nodes
	unsigned int u_x = m_width/(rows+1);
	unsigned int u_y = m_height/(columns+1);
	unsigned int s_x = (m_width%(rows+1))/2;
	unsigned int s_y = (m_height%(columns+1))/2;
	//Plot the lines connecting the nodes
	for(unsigned int i=u_x+s_x; i<m_width-(m_width%(rows+1))+s_x; i=i+u_x)
	{
		for(unsigned int j=u_y+s_y; j<m_height-(m_height%(columns+1)+u_y)+s_y; j++)
		{
			linguisticlpa[j][i] = LINECOLOUR;
		}
	}
	for(unsigned int j=u_y+s_y; j<m_height-(m_height%(columns+1))+s_y; j=j+u_y)
	{
		for(unsigned int i=u_x+s_x; i<m_width-(m_width%(rows+1)+u_x)+s_x; i++)
		{
			linguisticlpa[j][i] = LINECOLOUR;
		}
	}
	//Get the position of nodes on the SOM
	linguisticnodeposition.resize(rows);

	for(unsigned int i=0; i<rows; i++)
	{
		linguisticnodeposition[i].resize(columns);
		for(unsigned int j=0; j<columns; j++)
		{
			linguisticnodeposition[i][j].left = u_x*(i+1)-u_x/4+s_x;
			linguisticnodeposition[i][j].right = u_x*(i+1)+u_x/4+s_x;
			linguisticnodeposition[i][j].top = u_y*(j+1)-u_y/4+s_y;
			linguisticnodeposition[i][j].bottom = u_y*(j+1)+u_y/4+s_y;
		}
	}
	//Plot the nodes
	for(unsigned int i=0; i<rows; i++)
	{
		for(unsigned int j=0; j<columns; j++)
		{
			DrawLinguisticNode(linguisticnodeposition[i][j], BLANKCOLOUR);
		}
	}
	RECT updaterect = {LINGUISTICSTARTX, STARTY, LINGUISTICENDX, ENDY};
	InvalidateRect(&updaterect, 0);
	UpdateWindow();
	return;
}

//Update the colour of the node in the image view
void CCrossModalDialog::DrawImageNode(RECT rect, rgb nodecolour)
{
	//Update the colour of the nodes
	for(unsigned int i=(unsigned int)rect.left; i<=(unsigned int)rect.right; i++)
	{
		for(unsigned int j=(unsigned int)rect.top; j<=(unsigned int)rect.bottom; j++)
		{
			imagelpa[j][i] = nodecolour;
		}
	}
	//Reposition the rect into the dialog position
	rect.left += IMAGESTARTX;
	rect.right += IMAGESTARTX+1;
	rect.top += STARTY;
	rect.bottom += STARTY+1;
	//Update the view
	InvalidateRect(&rect, 0);
	UpdateWindow();
	return;
}

//Update the colour of the nodes in the linguistic view
void CCrossModalDialog::DrawLinguisticNode(RECT rect, rgb nodecolour)
{
	//Update the colour of the nodes
	for(unsigned int i=(unsigned int)rect.left; i<=(unsigned int)rect.right; i++)
	{
		for(unsigned int j=(unsigned int)rect.top; j<=(unsigned int)rect.bottom; j++)
		{
			linguisticlpa[j][i] = nodecolour;
		}
	}
	//Reposition the rect into the dialog position
	rect.left += LINGUISTICSTARTX;
	rect.right += LINGUISTICSTARTX+1;
	rect.top += STARTY;
	rect.bottom += ENDY+1;
	//Update the view
	InvalidateRect(&rect, 0);
	UpdateWindow();
	return;
}

//Handling when the left mouse button is pressed
void CCrossModalDialog::OnLButtonDown(UINT nFlags, CPoint point)
{
	//Verify the current position
	if(point.y<=STARTY||point.y>=ENDY)
		return;

	if(crossmodal==NULL)
		return;

	if(point.x>IMAGESTARTX&&point.x<IMAGEENDX)		//If click inside the image region
	{
		//Calculate the position clicked inside the image view
		unsigned int xposition = (unsigned int)(point.x-IMAGESTARTX);
		unsigned int yposition = (unsigned int)(point.y-STARTY);

		//Locate the node being clicked
		_2dpoint imagesomsize = crossmodal->GetMapSize1();
		unsigned int rows = imagesomsize.x;
		unsigned int columns = imagesomsize.y;
		unsigned int nodex = (unsigned int)-1;
		unsigned int nodey = (unsigned int)-1;
		for(unsigned int j=0; j<rows; j++)
			for(unsigned int i=0; i<columns; i++)
				if(xposition>=(unsigned int)imagenodeposition[i][j].left&&xposition<=(unsigned int)imagenodeposition[i][j].right&&
					yposition>=(unsigned int)imagenodeposition[i][j].top&&yposition<=(unsigned int)imagenodeposition[i][j].bottom)
				{
					nodex = i;
					nodey = j;
					continue;
				}
		//Check if a node is selected or not
		if(nodex==(unsigned int)-1||nodey==(unsigned int)-1)
			return;
		//Get the crossmodal links
		_2dpoint imageposition = {nodex, nodey};
		_2dpoint linguisticposition = crossmodal->GetCrossLink2(imageposition);
		//Check if there is any cross modal link to this node
		if(linguisticposition.x==(unsigned int)-1 || linguisticposition.y==(unsigned int)-1)
		{
			CCrossModalDialog::ResetDialog();
			DrawImageNode(imagenodeposition[nodex][nodey], SELECTCOLOUR);
			::AfxMessageBox(_T("No links for this node"), MB_OK, 0);
			return;
		}

		//plot the nodes and grab images and documents mapped to the two node from the database
		CCrossModalDialog::ActiveNodes(imageposition, linguisticposition);
	}

	//If click inside the linguistic region
	if(point.x>LINGUISTICSTARTX&&point.x<LINGUISTICENDX)
	{
		//Calculate the position clicked inside the linguistic view
		unsigned int xposition = (unsigned int)(point.x-LINGUISTICSTARTX);
		unsigned int yposition = (unsigned int)(point.y-STARTY);
		//Locate the node being clicked
		unsigned int rows, columns;
		_2dpoint linguisticsomsize = crossmodal->GetMapSize2();
		rows = linguisticsomsize.x;
		columns = linguisticsomsize.y;
		unsigned int nodex = (unsigned int)-1;
		unsigned int nodey = (unsigned int)-1;
		for(unsigned int j=0; j<rows; j++)
			for(unsigned int i=0; i<columns; i++)
				if(xposition>=(unsigned int)linguisticnodeposition[i][j].left&&xposition<=(unsigned int)linguisticnodeposition[i][j].right&&
					yposition>=(unsigned int)linguisticnodeposition[i][j].top&&yposition<=(unsigned int)linguisticnodeposition[i][j].bottom)
				{
					CCrossModalDialog::ResetDialog();
					DrawLinguisticNode(linguisticnodeposition[i][j], SELECTCOLOUR);
					nodex = i;
					nodey = j;
					continue;
				}
		//Varify if node is selected or not
		if(nodex==(unsigned int)-1||nodey==(unsigned int)-1)
			return;
		//Get the cross modal link
		_2dpoint linguisticposition = {nodex, nodey};
		_2dpoint imageposition = crossmodal->GetCrossLink1(linguisticposition);
		//Check if there is any cross modal link to this node
		if(imageposition.x==(unsigned int)-1 || imageposition.y==(unsigned int)-1)
		{
			DrawLinguisticNode(linguisticnodeposition[nodex][nodey], SELECTCOLOUR);
			::AfxMessageBox(_T("No links for this node"), MB_OK, 0);
			return;
		}

		//plot the nodes and grab images and documents mapped to the two node from the database
		CCrossModalDialog::ActiveNodes(imageposition, linguisticposition);
	}
	return;
}

//Set the recovery point for recover the image and linguistic view
void CCrossModalDialog::SetRecovery()
{
	//Image view
	for(int j=0; j<imageview.GetHeight(); j++)
		for(int i=0; i<imageview.GetWidth(); i++)
			imagelparecovery[j][i] = imagelpa[j][i];

	//Linguistic view
	for(int j=0; j<linguisticview.GetHeight(); j++)
		for(int i=0; i<linguisticview.GetWidth(); i++)
			linguisticlparecovery[j][i] = linguisticlpa[j][i];

	return;
}

//Train the system
void CCrossModalDialog::OnBnClickedCrossmodalTrain()
{
	//Open the database
	CImageAnnotation imagedatabase;
	try
	{
		imagedatabase.Open();
	}
	catch(CDBException* e)
	{
		e->ReportError();
		return;
	}
	//Get the image features from the database
	vector<vector<vector<double>>> imagefeatures;
	vector<vector<double>> linguisticfeatures;
	while(!imagedatabase.IsEOF())
	{
		string filepath(imagedatabase.m_Image.GetBuffer());
		string filename = string(&(filepath.c_str()[filepath.find_last_of('\\')+1]));
		if((imagedatabase.m_Feature.m_dwDataLength==0) || (imagedatabase.m_Linguistic.m_dwDataLength==0))	//If not feature existed
		{
			imagedatabase.MoveNext();
			continue;
		}
		try
		{
			//Save the image feature to file
			CFile cfile(CString("c:\\temp.dat"), CFile::modeCreate|CFile::modeWrite);
			LPSTR buffer = (LPSTR)GlobalLock(imagedatabase.m_Feature.m_hData);
			cfile.Write(buffer, (UINT)imagedatabase.m_Feature.m_dwDataLength);
			cfile.Close();
			vector<vector<double>> currentfeature;
			bf.LoadBinaryData(currentfeature, string("c:\\temp.dat"));	//Load the features from file

			//Save the linguistic feature to file and reload it into the vector
			cfile.Open(CString("c:\\temp.dat"), CFile::modeCreate|CFile::modeWrite);
			buffer = (LPSTR)GlobalLock(imagedatabase.m_Linguistic.m_hData);
			cfile.Write(buffer, (UINT)imagedatabase.m_Linguistic.m_dwDataLength);
			cfile.Close();
			vector<double> currentlinguistic;
			bf.LoadBinaryData(currentlinguistic, string("c:\\temp.dat"));

			//Store the features
			imagefeatures.push_back(currentfeature);
			linguisticfeatures.push_back(currentlinguistic);
		}
		catch(string excpetionmessage)
		{
			::AfxMessageBox(CString(excpetionmessage.c_str()), MB_OK, 0);
			return;
		}
		imagedatabase.MoveNext();
	}
	imagedatabase.Close();
	//If no feature is found
	/*-------------------------------Save the linguistic features------------------------------------*/
	//unsigned int x, y;
	//double** featurematrix = bf.VectorToPointer(linguisticfeatures, x, y);
	//int numberofchars;
	//char* chars = bf.DoubleMatrixToChar(featurematrix, x, y, 5, '\t', &numberofchars);
	//bf.stringToFile(CString(chars, numberofchars), _T("Save the features as ..."));
	/*---------------------------End of Saving the linguistic features-------------------------------*/
	if(imagefeatures.size()==0)
	{
		::AfxMessageBox(CString("No image found"), MB_OK, 0);
		return;
	}
	//Create the hierarchical cross modal and train it
	_3dpoint sizeofmap1 = {10, 10, (unsigned int)((double)imagefeatures[0].size()*(double)1.5)};	//Size of the map
	_2dpoint sizeofmap2 = {10, 10};
	vector<double> maxvalueofmap1;		//Min and max values
	vector<double> minvalueofmap1;
	vector<double> maxvalueofmap2;
	vector<double> minvalueofmap2;
	for(unsigned int i=0; i<(unsigned int)imagefeatures[0][0].size(); i++)
	{
		maxvalueofmap1.push_back(1.0);
		minvalueofmap1.push_back(0.5);
	}
	for(unsigned int i=0; i<(unsigned int)linguisticfeatures[0].size(); i++)
	{
		maxvalueofmap2.push_back(1.0);
		minvalueofmap2.push_back(0.5);
	}
	unsigned int trainingcycle = 10;
	vector<_2dpoint> winners1;
	vector<_2dpoint> winners2;
	winners1.resize(imagefeatures.size());
	winners2.resize(imagefeatures.size());

	try
	{
		//Create the network
		crossmodal = new CMultiscaleCrossModal(sizeofmap1, sizeofmap2, (unsigned int)imagefeatures[0][0].size(),
			(unsigned int)linguisticfeatures[0].size(), maxvalueofmap1, minvalueofmap1, maxvalueofmap2, minvalueofmap2, trainingcycle); //Constructor
		//Train the network
		crossmodal->NetTraining(imagefeatures, linguisticfeatures);
		//Save the network
		crossmodal->SaveCrossModalToFile(string(HOMEDIRECTORY)+string("data\\firstnet.dat"),
			string(HOMEDIRECTORY)+string("data\\secondnet.dat"),
			string(HOMEDIRECTORY)+string("data\\hebbian.dat"));	
//		linguisticprocessing->SaveCorpusToFile(string(HOMEDIRECTORY)+string("data\\corpus.txt");
		//Test the network
		for(unsigned int i=0; i<(unsigned int)imagefeatures.size(); i++)
		{
			winners1[i] = crossmodal->GetWinner1(imagefeatures[i]);
			winners2[i] = crossmodal->GetWinner2(linguisticfeatures[i]);
		}
	}
	catch(string exceptionmessage)
	{
		::AfxMessageBox(CString(exceptionmessage.c_str()), MB_OK, 0);
		return;
	}

	//Save results to the database
	try
	{
		imagedatabase.Open();
		imagedatabase.MoveFirst();
		unsigned int counter = 0;
		while(!imagedatabase.IsEOF())
		{
			imagedatabase.Edit();
			imagedatabase.m_LPositionX = winners2[counter].x;
			imagedatabase.m_LPositionY = winners2[counter].y;
			imagedatabase.m_PositionX = winners1[counter].x;
			imagedatabase.m_PositionY = winners1[counter].y;
			counter ++;
			imagedatabase.Update();
			imagedatabase.MoveNext();
		}
	}
	catch(CException* e)
	{
		e->ReportError();
		return;
	}

	////Get the number of images
	//unsigned int numberofimages = (unsigned int)imagefeatures.size();
	//vector<unsigned int> imagecluster;
	//imagecluster.resize(numberofimages);
	//vector<_3dpoint> imageposition;
	//imageposition.resize(numberofimages);

	////Create a hierarchical SOM, train it, and test it
	////Definition
	//vector<vector<vector<double>>> trainingweights;
	//vector<_3dpoint> trainingwinners;
	//unsigned int maxcycle = 1;
	//vector<double> maxvalue;	//Max values for initialization
	//vector<double> minvalue;		//MIn values for initialization
	//for(unsigned int i=0; i<(unsigned int)imagefeatures[0][0].size(); i++)
	//{
	//	maxvalue.push_back(1.0);
	//	minvalue.push_back(0.0);
	//}
	////Training and testing
	//try
	//{
	//	multiscalenet = new MultiscaleNet(16, 16, (unsigned int)imagefeatures[0].size()*2, (unsigned int)imagefeatures[0][0].size(), maxcycle,
	//		maxvalue, minvalue);	//Create the hierarchical SOM
	//	CCrossModalDialog::NormalizeData(imagefeatures, 2);
	//	for(unsigned int i=0; i<maxcycle; i++)
	//		multiscalenet->Training(imagefeatures, trainingwinners, trainingweights);		//Train the SOM
	//	for(unsigned int i=0; i<numberofimages; i++)		//Test the SOM using the image features
	//	{
	//		vector<vector<double>> testweight;
	//		multiscalenet->GetTestWinnerWeight(imagefeatures[i], imageposition[i], testweight);
	//		imagecluster[i] = imageposition[i].x*16+imageposition[i].y;
	//	}
	//	multiscalenet->SaveNetIntoFile(HOMEDIRECTORY+string("data\\crossmodal.dat"));	//Save the SOM to file
	//}
	//catch(string exceptionmessage)
	//{
	//	::AfxMessageBox(CString(exceptionmessage.c_str()), MB_OK, 0);
	//	return;
	//}

	//Save results to database
	//imagedatabase.MoveFirst();
	//unsigned int imagecounter = 0;
	//while(!imagedatabase.IsEOF())
	//{
	//	imagedatabase.Edit();
	//	imagedatabase.m_Cluster = (int)imagecluster[imagecounter];
	//	imagedatabase.m_PositionX = (int)imageposition[imagecounter].x;
	//	imagedatabase.m_PositionY = (int)imageposition[imagecounter].y;
	//	imagedatabase.m_PositionZ = (int)imageposition[imagecounter].z;
	//	try
	//	{
	//		imagedatabase.Update();
	//	}
	//	catch(CDBException* e)
	//	{
	//		e->ReportError();
	//		return;
	//	}
	//	imagedatabase.MoveNext();
	//	imagecounter ++;
	//}
	//imagedatabase.Close();

	//Plot the image and create recovery
	CCrossModalDialog::PlotImageSOM(sizeofmap1.x, sizeofmap1.y);
	CCrossModalDialog::PlotLinguisticSOM(sizeofmap2.x, sizeofmap2.y);
	for(int j=0; j<imageview.GetHeight(); j++)
	{
		for(int i=0; i<imageview.GetWidth(); i++)
		{
			imagelparecovery[j][i] = imagelpa[j][i];
			linguisticlparecovery[j][i] = linguisticlpa[j][i];
		}
	}

	//Close the database
	imagedatabase.Close();

	//Set the keywords for each node
	linguisticprocessing = new CLinguisticProcessing(string(HOMEDIRECTORY)+string("data\\corpus.txt"), LOGSPACE);
	CCrossModalDialog::SetKeywordsForNode();

	return;
}

//Normalize the input
void CCrossModalDialog::NormalizeData(std::vector<vector<vector<double> > > &input, unsigned int normalizescale)
{
	//Varify the size of the inputdata
	if(input.size()==0)
		throw string("No data in input");
	else if(input[0].size()==0)
		throw string("No data in first input");

	unsigned int size1 = (unsigned int)input.size();
	unsigned int size2 = (unsigned int)input[0].size();
	unsigned int size3 = (unsigned int)input[0][0].size();

	vector<vector<double>> meanvalue;
	vector<vector<double>> standarddeviation;
	meanvalue.resize(size2);
	standarddeviation.resize(size2);
	for(unsigned int i=0; i<size2; i++)
	{
		meanvalue[i].resize(size3);
		standarddeviation[i].resize(size3);
		for(unsigned int j=0; j<size3; j++)
		{
			meanvalue[i][j] = 0.0;
			standarddeviation[i][j] = 0.0;
		}
	}

	//Loop to get the mean
	for(unsigned int i=0; i<size1; i++)
	{
		if((unsigned int)input[i].size()!=size2)
			throw string("Size of second dimension not equal");
		for(unsigned int j=0; j<size2; j++)
		{
			if((unsigned int)input[i][j].size()!=size3)
				throw string("Size of third dimension not equal");
			for(unsigned int k=0; k<size3; k++)
			{
				meanvalue[j][k] += input[i][j][k];
			}
		}
	}

	for(unsigned int i=0; i<size2; i++)
	{
		for(unsigned int j=0; j<size3; j++)
		{
			meanvalue[i][j] /= (double)size1;
		}
	}

	//Calculate standard deviation
	for(unsigned int i=0; i<size1; i++)
		for(unsigned int j=0; j<size2; j++)
			for(unsigned int k=0; k<size3; k++)
				standarddeviation[j][k] += (input[i][j][k]-meanvalue[j][k])*(input[i][j][k]-meanvalue[j][k]);

	for(unsigned int i=0; i<size2; i++)
	{
		for(unsigned int j=0; j<size3; j++)
		{
			standarddeviation[i][j] = sqrt(standarddeviation[i][j]/((double)size1-1.0));
			if(standarddeviation[i][j] == 0)
				standarddeviation[i][j] = 1;
		}
	}

	//Normalize the data
	for(unsigned int i=0; i<size1; i++)
	{
		for(unsigned int j=0; j<size2; j++)
		{
			for(unsigned int k=0; k<size3; k++)
			{
				input[i][j][k] = (input[i][j][k]-meanvalue[j][k])/standarddeviation[j][k];
			}
		}
	}

	return;
}

//Reset the view of the image som
void CCrossModalDialog::ResetImageView()
{
	for(int j=0; j<imageview.GetHeight(); j++)
		for(int i=0; i<imageview.GetWidth(); i++)
			imagelpa[j][i] = imagelparecovery[j][i];

	RECT rect = {IMAGESTARTX, STARTY, IMAGEENDX, ENDY};
	InvalidateRect(&rect, 1);
	UpdateWindow();
}

//Reset the view of linguistic som
void CCrossModalDialog::ResetLinguisticView()
{
	for(int j=0; j<linguisticview.GetHeight(); j++)
		for(int i=0; i<linguisticview.GetWidth(); i++)
			linguisticlpa[j][i] = linguisticlparecovery[j][i];

	RECT rect = {LINGUISTICSTARTX, STARTY, LINGUISTICENDX, ENDY};
	InvalidateRect(&rect, 1);
	UpdateWindow();
}

void CCrossModalDialog::OnLbnSelchangeCrossmodalImagelist()
{
	//Get the current selected image and open in the childview window
	CListBox* listbox = (CListBox*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_IMAGELIST);
	CEdit* captionedit = (CEdit*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_CAPTION);
	CEdit* keywordedit = (CEdit*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_KEYWORDS);

	//check is there are new images added into the list
	if(newlist.size()==0)		//If no new images is addedd, open the captions for the existing images
	{
		int currentselection = listbox->GetCurSel();
		if(currentselection<0)
			return;

		CString filename;		//Filename of the image not including the path
		 listbox->GetWindowTextW(filename);
		((CChildFrame*)parent)->m_wndView.OnImageOpen(CString(imagelist[currentselection].c_str()), filename);
		//Open text file
		string captionpath = string(imagelist[currentselection].c_str(), imagelist[currentselection].size()-4);
		captionpath += ".txt";
		try
		{
			CFile cfile(CString(captionpath.c_str()), CFile::modeRead);
			char* filecontent = new char[(size_t)cfile.GetLength()];
			UINT nbyte = cfile.Read(filecontent, (UINT)cfile.GetLength());
			cfile.Close();
			captionedit->SetWindowTextW(CString(filecontent, nbyte));
			//Get the keywords
			vector<string> keywords = linguisticprocessing->GetKeywords(string(filecontent));
			CString keywordsfordialog;
			for(unsigned int i=0; i<keywords.size(); i++)
			{
				keywordsfordialog += CString(keywords[i].c_str());
				keywordsfordialog += CString("\r\n");
			}
			keywordedit->SetWindowTextW(keywordsfordialog);
			delete[] filecontent;
		}
		catch(CException* e)
		{
			e->ReportError();
			return;
		}
	}
	else		//generate new annotations for the selected image
	{
		//get the selected images
		int currentselect = listbox->GetCurSel();
		if(currentselect<0)
			return;
		CString filename;
		listbox->GetWindowTextW(filename);
		//open the image and get the wavelet features
		((CChildFrame*)parent)->m_wndView.OnImageOpen(CString(newlist[currentselect].c_str()), filename);
		vector<vector<double>> imagefeature = ((CChildFrame*)parent)->m_wndView.GetImageWaveletFeature(4, 3, 3);
		//find the winners and grab keywords for the image
		_2dpoint imageposition = crossmodal->GetWinner1(imagefeature);
		_2dpoint linguisticposition = crossmodal->GetCrossLink2(imageposition);
		if(linguisticposition.x==(unsigned int)-1 || linguisticposition.y==(unsigned int)-1)
		{
			::AfxMessageBox(CString("No keyword is suitable for this image"), MB_OK, 0);
			return;
		}
		CCrossModalDialog::ResetImageView();
		CCrossModalDialog::ResetLinguisticView();
		CCrossModalDialog::DrawImageNode(imagenodeposition[imageposition.x][imageposition.y], SELECTCOLOUR);
		CCrossModalDialog::DrawLinguisticNode(linguisticnodeposition[linguisticposition.x][linguisticposition.y], SELECTCOLOUR);
		keywordedit->SetWindowTextW(CString(keywordsfornode[linguisticposition.x][linguisticposition.y].c_str()));
	}
	return;
}

void CCrossModalDialog::OnBnClickedCrossmodalLoad()
{
	//Load the data
	crossmodal = new CMultiscaleCrossModal(string(HOMEDIRECTORY)+string("data\\firstnet.dat"),
			string(HOMEDIRECTORY)+string("data\\secondnet.dat"),
			string(HOMEDIRECTORY)+string("data\\hebbian.dat"));
	linguisticprocessing = new CLinguisticProcessing(string(HOMEDIRECTORY)+string("data\\corpus.txt"), LOGSPACE);
	CCrossModalDialog::SetKeywordsForNode();

	//Plot the image and create recovery
	_2dpoint sizeofmap1 = crossmodal->GetMapSize1();
	_2dpoint sizeofmap2 = crossmodal->GetMapSize2();
	CCrossModalDialog::PlotImageSOM(sizeofmap1.x, sizeofmap1.y);
	CCrossModalDialog::PlotLinguisticSOM(sizeofmap2.x, sizeofmap2.y);
	for(int j=0; j<imageview.GetHeight(); j++)
	{
		for(int i=0; i<imageview.GetWidth(); i++)
		{
			imagelparecovery[j][i] = imagelpa[j][i];
			linguisticlparecovery[j][i] = linguisticlpa[j][i];
		}
	}
	return;
}

void CCrossModalDialog::OnOK()
{
	return;
}

//Set the keyowrds for each node
void CCrossModalDialog::SetKeywordsForNode()
{
	//open the database
	CImageAnnotation imagedatabase;

	//Set keywords for every node
	_2dpoint mapsize = crossmodal->GetMapSize2();
	keywordsfornode.resize(mapsize.x);
	for(unsigned int i=0; i<(unsigned int)keywordsfornode.size(); i++)
	{
		keywordsfornode[i].resize(mapsize.y);
		for(unsigned int j=0; j<(unsigned int)keywordsfornode[i].size(); j++)
		{
			//query the database to get the documents mapped to the node
			CString requery("PositionX = ");
			requery += bf.douTostr(i);
			requery += CString(" AND PositionY = ");
			requery += bf.douTostr(j);
			//Combine the documents together
			CString nodestring;
			try
			{
				imagedatabase.Open();
				imagedatabase.m_strFilter = requery;
				imagedatabase.Requery();
				while(!imagedatabase.IsEOF())
				{
					nodestring += imagedatabase.m_Caption;
					nodestring += _T(" ");
					imagedatabase.MoveNext();
				}
				imagedatabase.Close();
			}
			catch(CDBException* e)
			{
				e->ReportError();
				return;
			}
			//get the frequency of keywords in the fused document
			CT2CA asciistring(nodestring);
			keywordsfornode[i][j] = linguisticprocessing->FindFrequentKeywords(string(asciistring), 5);
		}
	}
	imagedatabase.Close();
	return;
}

void CCrossModalDialog::OnLbnSelchangeCrossmodalLinguisticlist()
{
	//Get the current selected image and open in the childview window
	CListBox* listbox = (CListBox*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_LINGUISTICLIST);
	CEdit* captionedit = (CEdit*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_CAPTION);
	CEdit* keywordedit = (CEdit*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_KEYWORDS);
	int currentselection = listbox->GetCurSel();
	if(currentselection<0)
		return;

	CString filename;		//Filename of the image not including the path
	 listbox->GetWindowTextW(filename);
	((CChildFrame*)parent)->m_wndView.OnImageOpen(CString(linguisticlist[currentselection].c_str()), filename);
	//Open text file
	string captionpath = string(linguisticlist[currentselection].c_str(), linguisticlist[currentselection].size()-4);
	captionpath += ".txt";
	try
	{
		CFile cfile(CString(captionpath.c_str()), CFile::modeRead);
		char* filecontent = new char[(size_t)cfile.GetLength()];
		UINT nbyte = cfile.Read(filecontent, (UINT)cfile.GetLength());
		cfile.Close();
		captionedit->SetWindowTextW(CString(filecontent, nbyte));
		//Get the keywords
		vector<string> keywords = linguisticprocessing->GetKeywords(string(filecontent));
		CString keywordsfordialog;
		for(unsigned int i=0; i<keywords.size(); i++)
		{
			keywordsfordialog += CString(keywords[i].c_str());
			keywordsfordialog += CString("\r\n");
		}
		keywordedit->SetWindowTextW(keywordsfordialog);
		delete[] filecontent;
	}
	catch(CException* e)
	{
		e->ReportError();
		return;
	}
	return;
}

void CCrossModalDialog::OnBnClickedCrossmodalRetrieveimage()
{
	if(linguisticprocessing==NULL||crossmodal==NULL)
		return;
	//get the query string
	CEdit* queryedit = (CEdit*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_RETRIEVEKEYWORD);
	CString querystring;
	queryedit->GetWindowTextW(querystring);
	//convert to ascii and get the feature
	CT2CA asciistring(querystring);
	vector<double> queryfeature = linguisticprocessing->GetLinguisticFeature(string(asciistring));
	//get the mapping
	_2dpoint linguisticposition = crossmodal->GetWinner2(queryfeature);
	_2dpoint imageposition = crossmodal->GetCrossLink1(queryfeature);
	
	//plot the map and grab images and documents on the two maps
	CCrossModalDialog::ActiveNodes(imageposition, linguisticposition);
}

//Plot the activitated nodes and grab images and documents from the two maps
void CCrossModalDialog::ActiveNodes(_2dpoint imageposition, _2dpoint linguisticposition)
{
	//Reset the dialog
	CCrossModalDialog::ResetDialog();
	CListBox* listbox = (CListBox*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_IMAGELIST);
	CListBox* linguisticbox = (CListBox*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_LINGUISTICLIST);

	//Plot the colour of selected nodes
	DrawImageNode(imagenodeposition[imageposition.x][imageposition.y], SELECTCOLOUR);
	DrawLinguisticNode(linguisticnodeposition[linguisticposition.x][linguisticposition.y], SELECTCOLOUR);

	//Open the database and grab the images mapped to the same node from the database
	CImageAnnotation imagedatabase;
	CString requery("PositionX = ");
	requery += bf.douTostr(imageposition.x);
	requery += CString(" AND PositionY = ");
	requery += bf.douTostr(imageposition.y);
	try
	{
		imagedatabase.Open();
		imagedatabase.m_strFilter = requery;
		imagedatabase.Requery();
		imagelist.resize(0);
		while(!imagedatabase.IsEOF())
		{
			string filepath(imagedatabase.m_Image.GetBuffer());
			listbox->AddString(CString(&(filepath.c_str()[filepath.find_last_of('\\')+1])));
			imagelist.push_back(filepath);
			imagedatabase.MoveNext();
		}
		imagedatabase.Close();
	}
	catch(CDBException* e)
	{
		e->ReportError();
		return;
	}

	//Open the database and grab the documents mapped to the same node from the database
	requery = _T("LPositionX = ");
	requery += bf.douTostr(linguisticposition.x);
	requery += CString(" AND LPositionY = ");
	requery += bf.douTostr(linguisticposition.y);
	try
	{
		imagedatabase.Open();
		imagedatabase.m_strFilter = requery;
		imagedatabase.Requery();
		linguisticlist.resize(0);
		while(!imagedatabase.IsEOF())
		{
			string filepath(imagedatabase.m_Image.GetBuffer());
			linguisticbox->AddString(CString(&(filepath.c_str()[filepath.find_last_of('\\')+1])));
			linguisticlist.push_back(filepath);
			imagedatabase.MoveNext();
		}
		imagedatabase.Close();
	}
	catch(CDBException* e)
	{
		e->ReportError();
		return;
	}
}

//Reset the views
void CCrossModalDialog::ResetDialog()
{
	//Reset the dialog
	CCrossModalDialog::ResetImageView();
	CCrossModalDialog::ResetLinguisticView();
	CListBox* listbox = (CListBox*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_IMAGELIST);
	CListBox* linguisticbox = (CListBox*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_LINGUISTICLIST);
	CEdit* captionedit = (CEdit*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_CAPTION);
	CEdit* keywordedit = (CEdit*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_KEYWORDS);
	captionedit->SetWindowTextW(CString(""));
	keywordedit->SetWindowTextW(CString(""));
	listbox->ResetContent();
	linguisticbox->ResetContent();
	newlist.resize(0);
}

void CCrossModalDialog::OnBnClickedCrossmodalAddimage()
{
	if(crossmodal==NULL)
		return;
	//reset the views
	CCrossModalDialog::ResetDialog();
	CListBox* listbox = (CListBox*)CCrossModalDialog::GetDlgItem(IDC_CROSSMODAL_IMAGELIST);
	//Open an dialog to select multiple images
	newlist.resize(0);
	try
	{
		newlist = bf.SelectMultipleFiles(_T("(*.BMP; *.JPEG; *.TIF)|*.bmp;*.jpg;*.tif;*.tiff||"));
	}
	catch(string exceptionmessage)
	{
		::AfxMessageBox(CString(exceptionmessage.c_str()), MB_OK, 0);
		return;
	}
	//add the images into the list box
	for(unsigned int i=0; i<(unsigned int)newlist.size(); i++)
	{
		string filename(&(newlist[i].c_str()[newlist[i].find_last_of('\\')+1]));
		listbox->AddString(CString(filename.c_str()));
	}
	return;
}
